package com.example.design_pattern.strategy;

import java.util.ArrayList;
import java.util.List;

// 所谓策略，我理解的策略就是，算法
// 策略模式的结构
//策略模式主要包含以下几个角色：
//
//策略接口（Strategy）: 定义所有支持的算法的公共接口。
//具体策略（Concrete Strategy）: 实现了策略接口的具体算法。
//上下文（Context）: 使用一个具体策略对象来配置。上下文维护一个对策略对象的引用，并且可以调用策略对象定义的接口。
// 策略模式的优点
//简化代码: 通过消除条件语句，将相关算法分离成独立的类，简化代码结构。
//易于扩展: 可以独立地扩展新的算法而不影响现有系统。
//提高灵活性: 可以在运行时动态更改算法。
//策略模式的实现
// 我们通过一个简单的例子来展示策略模式的使用。假设我们有一个应用程序，可以对不同的支付方式进行支付。我们可以使用策略模式来实现这一点。
// 解释
//策略接口（PaymentStrategy）: 定义支付方法。
//具体策略（CreditCardPayment 和 PaypalPayment）: 实现支付方法的具体策略。
//上下文（ShoppingCart）: 根据用户选择的支付策略来进行支付操作。
//通过这种方式，ShoppingCart 可以灵活地使用不同的支付方式，而不需要修改自身的实现。这展示了策略模式的灵活性和扩展性。


//
// 策略接口
interface PaymentStrategy {
    void pay(int amount);
}


// 策略实现类
class CreditCardPayment implements PaymentStrategy {
    private String name;
    private String cardNumber;
    private String cvv;
    private String dateOfExpiry;

    public CreditCardPayment(String nm, String ccNum, String cvv, String expiry) {
        this.name = nm;
        this.cardNumber = ccNum;
        this.cvv = cvv;
        this.dateOfExpiry = expiry;
    }

    @Override
    public void pay(int amount) { // 具体策略之一
        System.out.println(amount + " paid with credit/debit card");
    }
}


// 策略实现类二
class PaypalPayment implements PaymentStrategy {
    private String emailId;
    private String password;

    public PaypalPayment(String email, String pwd) {
        this.emailId = email;
        this.password = pwd;
    }

    @Override
    public void pay(int amount) { // 具体策略之二
        System.out.println(amount + " paid using PayPal.");
    }
}



// 购物车。这是上下文???
class ShoppingCart {

    //
    private List<Item> items;

    // 构造函数
    public ShoppingCart() {
        this.items = new ArrayList<Item>();
    }

    // 添加
    public void addItem(Item item) {
        this.items.add(item);
    }

    // 移除
    public void removeItem(Item item) {
        this.items.remove(item);
    }

    //
    public int calculateTotal() {
        int sum = 0;
        for (Item item : items) {
            sum += item.getPrice();
        }
        return sum;
    }

    // 根据上下文购物车的cart.pay方法，其实也就是下面这个pay方法，被传入进来的入参，来决定使用哪个策略来支付。
    // cart.pay(new CreditCardPayment("Pankaj Kumar", "1234567890123456", "786", "12/15"));  使用信用卡支付
    // cart.pay(new PaypalPayment("myemail@example.com", "mypwd")); 使用paypal
    public void pay(PaymentStrategy paymentMethod) {
        int amount = calculateTotal();
        // PaymentStrategy paymentMethod的pay方法哦
        paymentMethod.pay(amount);
    }
}

// 商品
class Item {
    private String upcCode;
    private int price;

    public Item(String upc, int cost) {
        this.upcCode = upc;
        this.price = cost;
    }

    public String getUpcCode() {
        return upcCode;
    }

    public int getPrice() {
        return price;
    }
}




public class StrategyPatternDemo {
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart();

        Item item1 = new Item("1234", 10);
        Item item2 = new Item("5678", 40);

        cart.addItem(item1);
        cart.addItem(item2);

        // 支付使用信用卡
        // "Pankaj Kumar", "1234567890123456", "786", "12/15"这些参数只是这个策略它自己需要的一些参数而已
        cart.pay(new CreditCardPayment("Pankaj Kumar", "1234567890123456", "786", "12/15"));

        // 支付使用Paypal
        // "myemail@example.com", "mypwd"也只是这些策略它自己需要的参数而已
        cart.pay(new PaypalPayment("myemail@example.com", "mypwd"));
    }
}

